package cn.com.pc.content.service;

import cn.com.pc.content.domain.tag.Tag;
import cn.com.pc.content.domain.tag.TagRelation;
import cn.com.pc.content.domain.tag.TagRelationRepository;
import cn.com.pc.content.dto.PageForm;
import cn.com.pc.content.dto.PageResult;
import cn.com.pc.content.dto.TagRelationDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Service
public class TagRelationService {

    @Autowired
    private TagRelationRepository tagRelationRepository;


    /**
     * 新增或修改标签关系
     * @param tagRelationDTO
     * @param left
     * @param right
     * @return
     */
    public TagRelation createOrUpdateTagRelation(TagRelationDTO tagRelationDTO, Tag left, Tag right) {
        TagRelation tagRelation = new TagRelation();
        BeanUtils.copyProperties(tagRelationDTO, tagRelation);
        tagRelation.setRelationKey(TagRelation.TagRelationKey.builder().left(left).right(right).build());
        tagRelation = tagRelationRepository.save(tagRelation);
        return tagRelation;
    }


    /**
     * 删除标签关系
     * @param left
     * @param right
     */
    public void deleteTagRelation(Tag left, Tag right) {
        tagRelationRepository.deleteById(TagRelation.TagRelationKey.builder().left(left).right(right).build());
    }


    /**
     * 查询标签关系列表
     * @param tagRelationDTO
     * @param pageForm
     * @return
     */
    public PageResult<TagRelation> listTagRelationsByDTO(TagRelationDTO tagRelationDTO, PageForm pageForm) {
        // 联合主键处理
        TagRelation tagRelation = new TagRelation();
        Tag left = new Tag();
        Tag right = new Tag();
        TagRelation.TagRelationKey.TagRelationKeyBuilder builder = TagRelation.TagRelationKey.builder();
        if(tagRelationDTO.getLeftId() != null) {
            left.setId(tagRelationDTO.getLeftId());
            builder.left(left);
            if (StringUtils.hasLength(tagRelationDTO.getTagName()) && tagRelationDTO.getRightId() == null) {
                right.setName(tagRelationDTO.getTagName());
                builder.right(right);
            }
        }
        if (tagRelationDTO.getRightId() != null) {
            right.setId(tagRelationDTO.getRightId());
            builder.right(right);
            if (StringUtils.hasLength(tagRelationDTO.getTagName()) && tagRelationDTO.getLeftId() == null) {
                left.setName(tagRelationDTO.getTagName());
                builder.left(left);
            }
        }

        // 过滤
        if (left.getId() != null || right.getId() != null) {
            TagRelation.TagRelationKey tagRelationKey = builder.build();
            tagRelation.setRelationKey(tagRelationKey);
        }
        if (StringUtils.hasLength(tagRelationDTO.getRelation())) {
            tagRelation.setRelation(tagRelationDTO.getRelation());
        }
//        if (tagRelationDTO.getCreatedAt() != null) {
//            tagRelation.setCreatedAt(tagRelationDTO.getCreatedAt());
//        }

        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("relationKey.left.name", ExampleMatcher.GenericPropertyMatcher::contains)
                .withMatcher("relationKey.right.name", ExampleMatcher.GenericPropertyMatcher::contains);

        Example<TagRelation> example = Example.of(tagRelation, matcher);
        Pageable pageable = PageRequest.of(pageForm.getPageNum() - 1, pageForm.getPageSize());
        Page<TagRelation> tagRelationPage = tagRelationRepository.findAll(example, pageable);
        return PageResult.fromPage(tagRelationPage);
    }


    public List<Object> getTagParents(Long tagId, int limit) {
        List<Object> tagParents = new ArrayList<>();
        if (tagId != null) {
            TagRelationDTO tagRelationDTO = new TagRelationDTO();
            tagRelationDTO.setRightId(tagId);
            PageForm pageForm = new PageForm();
            pageForm.setPageSize(limit);
            PageResult<TagRelation> pageResult = listTagRelationsByDTO(tagRelationDTO, pageForm);
            List<TagRelation> tagRelations = pageResult.getContent();
            tagRelations.forEach(tagRelation -> {
                tagParents.add(new HashMap<String, Object>() {{
                    Tag left = tagRelation.getRelationKey().getLeft();
                    List<Object> parents = left == null ? Collections.emptyList() : getTagParents(left.getId(), limit);
                    put("tag", left);
                    put("parents", parents);
                }});
            });
        }
        return tagParents;
    }


    public List<Object> getTagSons(Long tagId, int limit) {
        List<Object> tagSons = new ArrayList<>();
        if (tagId != null) {
            TagRelationDTO tagRelationDTO = new TagRelationDTO();
            tagRelationDTO.setLeftId(tagId);
            PageForm pageForm = new PageForm();
            pageForm.setPageSize(limit);
            PageResult<TagRelation> pageResult = listTagRelationsByDTO(tagRelationDTO, pageForm);
            List<TagRelation> tagRelations = pageResult.getContent();
            tagRelations.forEach(tagRelation -> {
                tagSons.add(new HashMap<String, Object>() {{
                    Tag right = tagRelation.getRelationKey().getRight();
                    List<Object> sons = right == null ? Collections.emptyList() : getTagSons(right.getId(), limit);
                    put("tag", right);
                    put("sons", sons);
                }});
            });
        }
        return tagSons;
    }
}
